package com.shuai.blog.controller;

import com.shuai.blog.common.*;
import com.shuai.blog.entity.UserInfo;
import com.shuai.blog.entity.vo.UserInfoVO;
import com.shuai.blog.service.ArticleService;
import com.shuai.blog.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private ArticleService articleService;

    @RequestMapping("/register")
    public HttpResult register(UserInfo userInfo, String captcha, HttpServletRequest request) {
        //先检验验证码是否正确
        HttpSession session = request.getSession(false);
        String savedCaptcha = (String) session.getAttribute(AppConstant.CAPTCHA_KEY);
        if (savedCaptcha == null || !savedCaptcha.equals(captcha)) {
            return HttpResult.fail("验证码错误!");
        }
        if (userInfo == null ||
                !StringUtils.hasLength(userInfo.getUsername()) ||
                !StringUtils.hasLength(userInfo.getPassword()) ||
                !StringUtils.hasLength(userInfo.getNickname())) {
            return HttpResult.fail(-1, "非法参数");
        }
        //对密码进行加密
        userInfo.setPassword(PwdSaltingUtils.saltingEncrypt(userInfo.getPassword()));
        userService.register(userInfo);
        userInfo.setPassword(null);
        session.setAttribute(AppConstant.USER_SESSION_KEY, userInfo);
        return HttpResult.success(userInfo);
    }

    @Value("${photoPath}")
    private String photoPath;


//    @RequestMapping(value = "/login", method = RequestMethod.POST)
//    public HttpResult login(String username, String password, HttpServletRequest request) {
//        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
//            return HttpResult.fail(-1, "非法参数！");
//        }
//        UserInfo login = userService.login(username);
//        if (login != null) {
//            if (PwdSaltingUtils.verify(password, login.getPassword())) {
//                //存储用户信息
//                HttpSession session = request.getSession(true);
//                session.setAttribute(AppConstant.USER_SESSION_KEY, login);    //存储用户session信息，在用户访问其他页面时验证用户的身份信息
//                login.setPassword("");
//                return HttpResult.success(login);
//            }
//        }
//        return HttpResult.success(-1, null);
//    }

    /**
     * 登录校验 -- 冻结
     */

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public HttpResult login(String username, String password, HttpServletRequest request, String captcha) {
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password) || !StringUtils.hasLength(captcha)) {
            return HttpResult.fail(-1, "非法参数！");
        }
        //先看验证码是否正确
        if (!MyCaptchaUtils.verifyCaptcha(request, captcha)) {
            return HttpResult.fail(-1, "验证码错误");
        }
        UserInfo login = userService.login(username);
        if (login != null) {

            if (PwdSaltingUtils.verify(password, login.getPassword())) {
                //存储用户信息
                HttpSession session = request.getSession(true);
                session.setAttribute(AppConstant.USER_SESSION_KEY, login);    //存储用户session信息，在用户访问其他页面时验证用户的身份信息
                login.setPassword("");
                return HttpResult.success(login);
            } else {
                //密码错误
                //先查询下用户的state是否为5
                if (userService.getUserState(login.getUserId()) == AppConstant.NUM_OF_LOGINS) {
                    Timer timer = new Timer();
                    timer.schedule(new TimerTask() {
                        //5分钟后恢复用户的登陆状态
                        @Override
                        public void run() {
                            login.setState(1);
                            userService.updateStateByName(login);
                        }
                    }, AppConstant.FROZEN_TIME);
                    return HttpResult.fail(-2, "登陆失败，账号已冻结！请5分钟后重试！");
                } else {
                    login.setState(login.getState() + 1);
                    userService.updateStateByName(login);
                    return HttpResult.fail(-2, "登陆失败，您还可以重试" + (AppConstant.NUM_OF_LOGINS - login.getState() + 1) + "次");
                }
            }
        }
        return HttpResult.fail(-1, "用户名或密码错误！");
    }

    /**
     * 返回个人列表的用户信息
     */
    @RequestMapping("/info")
    public HttpResult getUserInfo(HttpServletRequest request) {
        UserInfoVO userInfoVO = new UserInfoVO();
        UserInfo userInfo = UserSessionUtils.getUserInfo(request);
        if (userInfo == null) {
            return HttpResult.fail(-1, "请求非法");
        }
        //这是Spring提供的深拷贝的方法。其中第一个参数为源对象，第二个参数为目标对象。将两个对象汇中同名的成员属性进行拷贝赋值
        BeanUtils.copyProperties(userInfo, userInfoVO);
        userInfoVO.setArtCount(articleService.getCountByUserId(userInfo.getUserId()));
        return HttpResult.success(userInfoVO);
    }

    @RequestMapping("/logout")
    public HttpResult logout(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session == null) {
            return HttpResult.fail(-1, "非法请求");
        }
        session.removeAttribute(AppConstant.USER_SESSION_KEY);
        return HttpResult.success(200, null);
    }

    @RequestMapping("/get_id")
    public HttpResult getUserById(Integer userId) {
        if (userId == null || userId <= 0) {
            return HttpResult.fail(-1, "参数非法");
        }
        UserInfoVO userInfoVO = new UserInfoVO();
        UserInfo userById = userService.getUserById(userId);
        BeanUtils.copyProperties(userById, userInfoVO);
        userInfoVO.setArtCount(articleService.getCountByUserId(userId));
        return HttpResult.success(userInfoVO);
    }

    @RequestMapping("/nick")
    public HttpResult updateNickName(HttpServletRequest request, UserInfo userInfo) {
        if (userInfo == null || !StringUtils.hasLength(userInfo.getNickname()) || userInfo.getNickname().length() > 64) {
            return HttpResult.fail(-1, "非法参数");
        }
        UserInfo sessionUser = UserSessionUtils.getUserInfo(request);
        if (sessionUser == null || sessionUser.getUserId() == null) {
            return HttpResult.fail(-1, "非法请求");
        }
        userInfo.setUserId(sessionUser.getUserId());
        int affect = userService.updateNickName(userInfo);
        //更新session会话中的用户信息(这步忘了找了好久...😄)
        sessionUser.setNickname(userInfo.getNickname());
        return HttpResult.success(affect);
    }

    @RequestMapping("/up_pwd")
    public HttpResult updatePassword(HttpServletRequest request, String oldPassword, String newPassword) {
        if (!StringUtils.hasLength(oldPassword) || !StringUtils.hasLength(newPassword) || oldPassword.equals(newPassword)) {
            return HttpResult.fail(-1, "非法参数");
        }
        UserInfo userInfo = UserSessionUtils.getUserInfo(request);
        if (userInfo == null || userInfo.getUserId() == null) {
            return HttpResult.fail(-1, "非法请求，请登录！");
        }
        UserInfo login = userService.login(userInfo.getUsername());
        //验证旧密码和用户原来的密码是否相同
        if (!PwdSaltingUtils.verify(oldPassword, login.getPassword())) {
            return HttpResult.fail("旧密码不正确！无法修改！");
        }

        userInfo.setPassword(PwdSaltingUtils.saltingEncrypt(newPassword));
        int affect = userService.updatePassword(userInfo);
        //销毁该用户的session对象，让其用修改后的密码重新登陆
        request.getSession(false).removeAttribute(AppConstant.USER_SESSION_KEY);
        return HttpResult.success(affect);
    }


    @RequestMapping("/upd_photo")
    public HttpResult updatePhoto(@RequestPart("updatePhoto") MultipartFile multipartFile, HttpServletRequest request) {
        //先检查参数的合法性
        UserInfo userInfo = UserSessionUtils.getUserInfo(request);
        if (userInfo == null || userInfo.getUserId() == null) {
            return HttpResult.fail(-1, "非法请求");
        }
        String originalFilename = multipartFile.getOriginalFilename();//得到上传文件名
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));   //拿到上传文件的后缀
        if (!(".png".equals(suffix) || ".jpg".equals(suffix) || ".jpep".equals(suffix))) {
            return HttpResult.fail("文件格式错误");
        }
        String finalFileName = UUID.randomUUID().toString().replaceAll("-", "") + suffix;    //得到最终存储的文件名
        String finalSavePath = photoPath + finalFileName; //得到最终存储路径
        try {
            multipartFile.transferTo(new File(finalSavePath));
            //将文件名保存到用户表的photo字段上
            userService.updatePhoto(userInfo.getUserId(), "img/" + finalFileName);
            //更改session会话对象的用户信息
            userInfo.setPhoto("img/" + finalFileName);
        } catch (IOException e) {
            return HttpResult.fail(-1, "上传失败，请稍后重试！");
        }
        return HttpResult.success("img/" + finalFileName);
    }


    @RequestMapping("/for_pass_name")
    public HttpResult getConfidentialityAndAnswer(String username) {
        if (username == null || username.length() > 128) {
            return HttpResult.fail(-1, "非法参数");
        }
        UserInfo userInfo = userService.getConfidentialityAndAnswer(username);
        if (userInfo != null) {
            //将密保答案置空
            userInfo.setConAnswer(null);
            return HttpResult.success(userInfo);
        }
        return HttpResult.fail("用户不存在");
    }

    @RequestMapping("/for_pass_ans")
    public HttpResult updateByAnswer(UserInfo userInfo) {
        if (userInfo == null
                || !StringUtils.hasLength(userInfo.getConAnswer())
                || !StringUtils.hasLength(userInfo.getUsername())) {
            return HttpResult.fail("非法参数");
        }
        //利用用户名查询用户的密保信息
        UserInfo userOut = userService.getConfidentialityAndAnswer(userInfo.getUsername());
        if (userOut == null) {
            return HttpResult.fail("用户不存在！");
        } else if (!userOut.getConAnswer().equals(userInfo.getConAnswer())) {
            return HttpResult.fail("密保问题不正确！");
        } else {
            return HttpResult.success("");  //验证通过
        }
    }

    @RequestMapping("/for_pass_update")
    public HttpResult updatePwdNyAnswer(UserInfo userInfo) {
        if (userInfo == null
                || !StringUtils.hasLength(userInfo.getPassword())
                || !StringUtils.hasLength(userInfo.getConAnswer())
                || !StringUtils.hasLength(userInfo.getUsername())) {
            return HttpResult.fail("非法参数");
        }
        //对用户填写的新密码进行加密
        userInfo.setPassword(PwdSaltingUtils.saltingEncrypt(userInfo.getPassword()));
        int affect = userService.updatePwdByAnswer(userInfo);
        if (affect == 1) {
            return HttpResult.success(1);
        }
        return HttpResult.fail("修改失败，请重试！");
    }

    /**
     * 返回给前端登录时的验证码信息
     */
    @RequestMapping("/captcha")
    public void retCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
        MyCaptchaUtils.sendCaptcha(request, response);
    }


    @RequestMapping("/ca_loaded")
    public HttpResult getCaptcha(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session == null) {
            return HttpResult.fail(-1, "验证码填充失败！");
        }
        return HttpResult.success(session.getAttribute(AppConstant.CAPTCHA_KEY));
    }


    @GetMapping("/is_login")
    public HttpResult isLogin(HttpServletRequest request) {
        UserInfo userInfo = UserSessionUtils.getUserInfo(request);
        if (userInfo != null) {
            return HttpResult.success("logined");
        }
        return HttpResult.fail("un_login");
    }

}
